package com.bjy.qa.controller.functionaltest;

import com.bjy.qa.entity.Response;
import com.bjy.qa.entity.functionaltest.*;
import com.bjy.qa.entity.tools.Task;
import com.bjy.qa.service.functionaltest.IStepService;
import com.bjy.qa.service.functionaltest.ITestCaseService;
import com.bjy.qa.service.tools.ITaskManagerService;
import com.bjy.qa.util.security.SecurityUtils;
import com.rslai.commons.util.excel.ExcelWrite;
import com.rslai.commons.util.excel.Head;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/ft/testCase")
@Validated
@Api(tags = "测试用例")
public class TestCaseController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    ITestCaseService iTestCaseService;

    @Resource
    IStepService iStepService;

    @Resource
    ITaskManagerService iTaskManagerService;

    @RequestMapping(value = "/add", method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value = "添加测试用例", notes = "添加测试用例")
    public Response<Integer> add(@RequestBody @Valid TestCase testCase) throws Exception {
        logger.info("添加测试用例：{}", testCase);
        Response response = Response.success(iTestCaseService.add(testCase));
        logger.info("添加测试用例，成功 {}", response);
        return response;
    }

    @ApiOperation(value = "导入测试用例", notes = "导入测试用例")
    @ResponseBody
    @RequestMapping(value = "/fileImport", method = {RequestMethod.GET})
    public Response<Object> fileImport(@NotNull(message = "filePath: filePath字段必填") String filePath, @NotNull(message = "projectId: projectId字段必填") Long projectId) {
        logger.info("批量导入用例，路径为：{}", filePath);
        Task task = iTaskManagerService.newTask(); // 创建任务

        Map<String, String> map = new HashMap<>();
        map.put("taskId", task.getTaskId());
        map.put("filePath", filePath);
        iTestCaseService.fileImport(task.getTaskId(), filePath, projectId, SecurityUtils.getCurrentUserName()); // 异步导入测试用例
        Response response = Response.successAsync(map);

        logger.info("{}", response);
        return response;
    }

    @ApiOperation(value = "导出测试用例", notes = "导出测试用例")
    @ResponseBody
    @RequestMapping(value = "/export", method = {RequestMethod.POST})
    public Response<Object> export(@RequestBody @Valid ExportDTO exportDTO) {
        logger.info("导出测试用例 {}", exportDTO);
        Task task = iTaskManagerService.newTask(); // 创建任务

        Map<String, String> map = new HashMap<>();
        map.put("taskId", task.getTaskId());
        iTestCaseService.export(task.getTaskId(), exportDTO); // 异步导出测试用例
        Response response = Response.successAsync(map);

        logger.info("导出测试用例，成功 {}", response);
        return response;
    }

    @ApiOperation(value = "测试用例模版下载", notes = "测试用例模版下载")
    @ResponseBody
    @RequestMapping(value = "/getManualTemplate", method = {RequestMethod.GET})
    public void getManualTemplate(HttpServletResponse response) throws IOException {
        logger.info("测试用例模版下载");
        response.reset();
        response.setContentType("application/octet-stream"); // 设置文件类型
        response.setHeader("Access-Control-Allow-Origin", "*"); // 允许跨域访问
        response.setHeader("Access-Control-Allow-Credentials", "true"); // 是否支持cookie跨域
        response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("manual_use_case_template.xls", "UTF-8")); // 设置文件名
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition"); // 允许跨域访问的 header

        ServletOutputStream outputStream = response.getOutputStream();
        try {
            ExcelWrite excelWrite = new ExcelWrite();
            excelWrite.addHead(new Head(0, "用例编号", 20, null));
            excelWrite.addHead(new Head(1, "用例分类", 50, null));
            excelWrite.addHead(new Head(2, "优先级", 8, null));
            excelWrite.addHead(new Head(3, "用例名称", 30, null));
            excelWrite.addHead(new Head(4, "前置条件", 20, null));
            excelWrite.addHead(new Head(5, "操作步骤", 30, null));
            excelWrite.addHead(new Head(6, "预期结果", 30, null));
            excelWrite.addHead(new Head(7, "设计者", 8, null));

            ArrayList<String> userCase = new ArrayList<>();
            userCase.add("USER-LOGIN-001");
            userCase.add("用户模块/登录");
            userCase.add("P2");
            userCase.add("用户名不允许为空");
            userCase.add("存在账号 zhangsan");
            userCase.add("打开登录页面\n不输入用户名\n输入密码 123456\n点击登录按钮");
            userCase.add("\r\n\r\n\r\n提示“用户名不允许为空”");
            userCase.add("李四");
            excelWrite.addBody(userCase);

            excelWrite.write(outputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != outputStream) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        logger.info("测试用例模版下载，成功");
    }

    @RequestMapping(value = "/selectById", method = {RequestMethod.GET})
    @ResponseBody
    @ApiOperation(value = "根据 ID 查询测试用例", notes = "根据 ID 查询测试用例")
    public Response<Api> selectById(@NotNull(message = "ID: id字段必填") Long id) {
        logger.info("根据 ID 查询测试用例，id: {}", id);
        Response response = Response.success(iTestCaseService.selectById(id));
        logger.info("{}", response);
        return response;
    }

    @RequestMapping(value = "/update", method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value = "修改测试用例", notes = "修改测试用例")
    public Response<Integer> update(@RequestBody @Valid TestCase testCase) throws Exception {
        logger.info("修改测试用例：{}", testCase);
        Response response = Response.success(iTestCaseService.update(testCase));
        logger.info("修改测试用例，成功 {}", response);
        return response;
    }

    @RequestMapping(value = "/delete", method = {RequestMethod.GET})
    @ResponseBody
    @ApiOperation(value = "删除测试用例", notes = "删除测试用例")
    public Response<Integer> delete(@NotNull(message = "ID: id字段必填") Long id) {
        logger.info("删除测试用例，ID：" + id);
        Response response = Response.success(iTestCaseService.delete(id));
        logger.info("{}", response);
        return response;
    }

    @RequestMapping(value = "/saveOrUpdateBatch", method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value = "批量新增和修改测试用例", notes = "批量新增和修改测试用例")
    public Response<List<TestCase>> saveOrUpdateBatch(@RequestBody @Valid List<TestCase> testCases) {
        logger.info("批量新增和修改测试用例：{}", testCases);
        Response response = Response.success(iTestCaseService.saveOrUpdateBatch(testCases));
        logger.info("批量新增和修改测试用例，成功 {}", response);
        return response;
    }

    @RequestMapping(value = "/selectByCatalogId", method = {RequestMethod.GET})
    @ResponseBody
    @ApiOperation(value = "根据 目录ID 查询该目录下的测试用例", notes = "根据 目录ID 查询改目录下的测试用例")
    public Response<List<TestCase>> selectByCatalogId(@NotNull(message = "projectId: 项目id字段必填") Long projectId,@NotNull(message = "catalogId: 目录id字段必填") Long catalogId) {
        logger.info("根据 目录ID 查询改目录下的测试用例，项目id：{}, 目录id: {}", projectId, catalogId);
        Response response = Response.success(iTestCaseService.selectByCatalogId(projectId, catalogId));
        logger.info("{}", response);
        return response;
    }

    @RequestMapping(value = "/search", method = {RequestMethod.POST})
    @ResponseBody
    @ApiOperation(value = "搜索测试用例", notes = "搜索测试用例")
    public Response<List<TestCase>> search(@RequestBody @Valid SearchDTO searchDTO) {
        logger.info("搜索测试用例，{}", searchDTO);
        Response response = Response.success(iTestCaseService.search(searchDTO));
        logger.info("搜索测试用例，成功 {}", response);
        return response;
    }

    @ResponseBody
    @RequestMapping(value = "/testCaseDebug", method = {RequestMethod.POST})
    @ApiOperation(value = "发送 TestCase 调试请求", notes = "发送 TestCase 调试请求")
    public Response<TestSuite> testCaseDebug(@RequestBody @Valid TestCaseDebugDTO testCaseDebugDTO) {
        logger.info("发送 TestCase 调试请求：{}", testCaseDebugDTO);
        String runUser = SecurityUtils.getCurrentUserName();
        Response response = Response.success(iTestCaseService.testCaseDebug(testCaseDebugDTO, runUser));
        logger.info("发送 TestCase 调试请求，成功。{}", response);
        return response;
    }

}
